package com.nowcoder.topic.dp.hard;

/**
 * NC369 [NOIP2002 普及组] 过河卒
 * @author d3y1
 */
public class NC369{
    private boolean[][] isHorsePoint;
    private final int[] dx = new int[]{1, 1, -1, -1, 2, 2, -2, -2};
    private final int[] dy = new int[]{2, -2, 2, -2, 1, -1, 1, -1};

    /**
     * 代码中的类名、方法名、参数名已经指定，请勿修改，直接返回方法规定的值即可
     *
     *
     * @param n int整型 棋盘行数
     * @param m int整型 棋盘列数
     * @param x int整型 马的横坐标
     * @param y int整型 马的纵坐标
     * @return int整型
     */
    public int crossRiver (int n, int m, int x, int y) {
        return solution(n, m, x, y);
    }

    /**
     * 动态规划
     *
     * dp[i][j]表示卒从点A(0,0)能够到达点(i,j)的路径条数
     *
     *            { 0                        , isHorsePoint[i][j]=true
     *            { 1                        , isHorsePoint[i][j]=false && i=0 && j=0
     * dp[i][j] = { dp[i][j-1]               , isHorsePoint[i][j]=false && i=0 && j>0
     *            { dp[i-1][j]               , isHorsePoint[i][j]=false && i>0 && j=0
     *            { dp[i][j-1] + dp[i-1][j]  , isHorsePoint[i][j]=false && i>0 && j>0
     *
     * @param n
     * @param m
     * @param x
     * @param y
     * @return
     */
    private int solution(int n, int m, int x, int y){
        isHorsePoint = new boolean[n+1][m+1];
        markHorsePoint(n, m, x, y);

        int[][] dp = new int[n+1][m+1];

        for(int i=0; i<=n; i++){
            for(int j=0; j<=m; j++){
                if(!isHorsePoint[i][j]){
                    if(i==0 && j==0){
                        dp[i][j] = 1;
                    }else if(i==0 && j>0){
                        dp[i][j] = dp[i][j-1];
                    }else if(i>0 && j==0){
                        dp[i][j] = dp[i-1][j];
                    }else{
                        dp[i][j] = dp[i][j-1] + dp[i-1][j];
                    }
                }
            }
        }

        return dp[n][m];
    }

    /**
     * 标记马点: 马所在点 + 马跃控点
     * @param n
     * @param m
     * @param x
     * @param y
     */
    private void markHorsePoint(int n, int m, int x, int y){
        // 马所在点
        if(isValid(n, m, x, y)){
            isHorsePoint[x][y] = true;
        }
        // 马跃控点
        for(int i=0; i<8; i++){
            if(isValid(n, m, x+dx[i], y+dy[i])){
                isHorsePoint[x+dx[i]][y+dy[i]] = true;
            }
        }
    }

    /**
     * 是否合法: 坐标(x,y)
     * @param n
     * @param m
     * @param x
     * @param y
     * @return
     */
    private boolean isValid(int n, int m, int x, int y){
        if(x<0 || n<x || y<0 || m<y){
            return false;
        }

        return true;
    }
}